package com.workcell.workdata.xthings.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.workcell.workdata.common.core.util.R;
import com.workcell.workdata.xthings.api.feign.RemoteIotOpenService;
import com.workcell.workdata.xthings.constant.CodeChainnumUseStateEnum;
import com.workcell.workdata.xthings.constant.DeviceRunEventEnum;
import com.workcell.workdata.xthings.constant.HardwareStateEnum;
import com.workcell.workdata.xthings.constant.HardwareTypeEnum;
import com.workcell.workdata.xthings.dto.XthingsTvVo;
import com.workcell.workdata.xthings.entity.BaseTvBox;
import com.workcell.workdata.xthings.entity.CodeChainnum;
import com.workcell.workdata.xthings.entity.CodeTvBox;
import com.workcell.workdata.xthings.entity.DeviceRunLog;
import com.workcell.workdata.xthings.mapper.CodeChainnumMapper;
import com.workcell.workdata.xthings.mapper.CodeTvBoxMapper;
import com.workcell.workdata.xthings.service.BaseTvBoxService;
import com.workcell.workdata.xthings.service.CodeTvBoxService;
import com.workcell.workdata.xthings.service.DeviceRunLogService;
import com.workcell.workdata.xthings.service.factory.CodeBaseService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 流量计二维码
 *
 * @author 廖博文
 * @date 2022-11-28 10:15:36
 */
@Service
public class CodeTvBoxServiceImpl extends ServiceImpl<CodeTvBoxMapper, CodeTvBox> implements CodeTvBoxService, CodeBaseService {

	@Resource
	private BaseTvBoxService baseTvBoxService;
	@Resource
	private RemoteIotOpenService remoteIotOpenService;
	@Resource
	private CodeChainnumMapper codeChainnumMapper;
	@Resource
	private DeviceRunLogService deviceRunLogService;

	/**
	 * 保存二维码基本快照信息
	 * @param codeChainnum
	 * @return
	 */
	@Override
	public Boolean saveCodeBaseInfo(CodeChainnum codeChainnum) {
		// 查询硬件信息
		LambdaQueryWrapper<BaseTvBox> baseTvBoxCondition = new QueryWrapper<BaseTvBox>().lambda()
				.eq(BaseTvBox::getId,Long.valueOf(codeChainnum.getBaseId()));
		BaseTvBox baseFlowmeter = baseTvBoxService.getOne(baseTvBoxCondition);
		if (ObjectUtil.isEmpty(baseFlowmeter)){
			return false;
		}
		// 添加二维码快照信息
		CodeTvBox saveBean = new CodeTvBox();
		BeanUtil.copyProperties(baseFlowmeter,saveBean, "createBy","createTime","updateBy","updateTime");
		saveBean.setCodeId(codeChainnum.getCodeId());
		saveBean.setChainNum(codeChainnum.getChainNum());
		saveBean.setDeviceNo(codeChainnum.getDeviceNo());
		saveBean.setTbId(Long.valueOf(codeChainnum.getBaseId()));
		saveBean.setTbName(codeChainnum.getHardwareName());
		return this.save(saveBean);
	}

	/**
	 * 获取硬件清单
	 * @return
	 */
	@Override
	public List<JSONObject> getHardwareList() {
		LambdaQueryWrapper<BaseTvBox> lambdaQueryWrapper = Wrappers.lambdaQuery(BaseTvBox.class);
		lambdaQueryWrapper.eq(BaseTvBox::getState, HardwareStateEnum.INUSE.getCode());
		return baseTvBoxService.list(lambdaQueryWrapper).stream().map(i -> {
			JSONObject resultBean = new JSONObject();
			resultBean.put("baseId",String.valueOf(i.getId()));
			resultBean.put("manufacturer",i.getManufacturer());
			resultBean.put("hardwareName",i.getName());
			return resultBean;
		}).collect(Collectors.toList());
	}

	/**
	 * 查询硬件基本信息
	 * @param baseIds
	 * @return
	 */
	@Override
	public Object getHardwareBase(String baseIds) {
		List<String> baseList = Arrays.asList(baseIds.split(","));
		LambdaQueryWrapper<BaseTvBox> baseTvBoxCondition = new QueryWrapper<BaseTvBox>().lambda()
				.in(CollectionUtil.isNotEmpty(baseList),BaseTvBox::getId,baseList);
		List<BaseTvBox> baseTvBoxList = baseTvBoxService.list(baseTvBoxCondition);
		return baseTvBoxList;
	}

	/**
	 * 查询硬件快照信息
	 * @param codeId
	 * @return
	 */
	@Override
	public Object getHardwareInfo(String codeId) {
		return this.getById(codeId);
	}

	@Override
	public Boolean updatePanel(XthingsTvVo.BoardVo boardVo) {
		CodeTvBox tvBoxPanel = getByDeviceNo(boardVo.getDeviceNo());
		if(null == tvBoxPanel){
			log.error("更新看板失败,查不到数据");
			return false;
		}
		LambdaUpdateWrapper<CodeTvBox> lambdaUpdateWrapper = Wrappers.lambdaUpdate(CodeTvBox.class)
				.eq(CodeTvBox::getCodeId, tvBoxPanel.getCodeId())
				.set(CodeTvBox::getPanelContent, boardVo.getJsonUrlList());
		if(1 == boardVo.getUrlList().size()){
			lambdaUpdateWrapper.set(CodeTvBox::getPanelPlaybackCycle, null);
		}else if(1 < boardVo.getUrlList().size() && ObjectUtil.isNotEmpty(boardVo.getPlaybackCycle())){
			lambdaUpdateWrapper.set(CodeTvBox::getPanelPlaybackCycle, boardVo.getPlaybackCycle());
		}
		return this.update(lambdaUpdateWrapper);
	}

	@Override
	public CodeTvBox getByDeviceNo(String deviceNo) {
		LambdaQueryWrapper<CodeTvBox> tvBoxPanelCondition = new QueryWrapper<CodeTvBox>().lambda().eq(CodeTvBox::getChainNum, deviceNo);
		return this.getOne(tvBoxPanelCondition);
	}

	@Override
	public Long getBindRent(String deviceNo){
		return this.baseMapper.getBindRent(deviceNo);
	}

	//@Transactional(rollbackFor = Exception.class)
	//@SneakyThrows
	@Override
    public R unbindTenant(String deviceNo) {
		CodeChainnum codeChainnum = codeChainnumMapper.getByChainnumAndHardwareType(deviceNo, HardwareTypeEnum.TV_BOX.getCode());
		if(null == codeChainnum){
			return R.failed("设备不存在。");
		}
		if(ObjectUtil.isEmpty(getBindRent(deviceNo))){
			R.failed("未绑定租户，请先绑定");
		}
		LambdaUpdateWrapper<CodeTvBox> lambdaUpdateWrapper = Wrappers.lambdaUpdate(CodeTvBox.class)
				.eq(CodeTvBox::getChainNum, deviceNo)
				.set(CodeTvBox::getPanelPlaybackCycle, null)
				.set(CodeTvBox::getPanelContent, null)
				.set(CodeTvBox::getRentId, null)
				.set(CodeTvBox::getRentName, null);
		this.update(lambdaUpdateWrapper);

		LambdaUpdateWrapper<CodeChainnum> chainnumLambdaUpdateWrapper = Wrappers.lambdaUpdate(CodeChainnum.class)
				.eq(CodeChainnum::getChainNum, deviceNo)
				.set(CodeChainnum::getUseState, CodeChainnumUseStateEnum.INIT.getCode())
				.set(CodeChainnum::getLastOnlineTime, null)
				.set(CodeChainnum::getActiveTime, null);
		codeChainnumMapper.update(null, chainnumLambdaUpdateWrapper);
		//解绑移除
		remoteIotOpenService.removeUser(deviceNo);
		//操作日记
		DeviceRunLog deviceRunLog = new DeviceRunLog();
		deviceRunLog.setChainNum(deviceNo);
		deviceRunLog.setHardwareType(HardwareTypeEnum.TV_BOX.getCode());
		deviceRunLog.setDeviceNo(codeChainnum.getDeviceNo());
		deviceRunLog.setManufacturerCode(codeChainnum.getManufacturerCode());
		deviceRunLog.setEventType(DeviceRunEventEnum.OPERATION.getCode());
		deviceRunLog.setStartTime(LocalDateTime.now());
		deviceRunLog.setInputParam("TV重置成功");
		deviceRunLogService.save(deviceRunLog);
        return R.ok();
    }
}
